package MVC.view;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeSelectionModel;

import myAsm.MyClassNode;
import myAsm.MyJarNode;
import myAsm.MyMethodNode;
import myAsm.MyPackageNode;

import org.jdesktop.swingx.JXImagePanel;
import org.jdesktop.swingx.JXTitledPanel;
import org.jdesktop.swingx.border.DropShadowBorder;
import org.jdesktop.swingx.treetable.DefaultMutableTreeTableNode;
import org.jdesktop.swingx.treetable.DefaultTreeTableModel;

import MVC.controller.ControllerPatternFinder;
import MVC.events.ProgressChangedEvent;
import MVC.events.ResultArrivedEvent;
import MVC.events.TextChangedEvent;
import MVC.listeners.ReturnListener;
import MVC.view.returnframe.ReturnFrame;

public class JTreeWindow extends ViewPatternFinder implements TreeSelectionListener, ReturnListener{

	private JFrame frame = new JFrame();
	private JPanel container = new JPanel();
	private JTree tree = null;
	private JButton scanBouton = new JButton("Scan");
	private JButton button = new JButton("Parcourir");
	private JLabel label3 = new JLabel("Jar :");
	private JTextField jtf = new JTextField("Jar Path");
	private JTextArea logText = new JTextArea("");
	private JButton button2 = new JButton("Save");
	private JProgressBar progressBar = new JProgressBar(0, 100);
	private ErrorBox error = null;
	private Color colBack = new Color(125,125,125,50);
	private Color colFront = Color.white;
	private final static String newline = "\n";
	private MyTreeNode root = new MyTreeNode("Root");
	private ArrayList<JCheckBox> testToRun =  new ArrayList<JCheckBox>();
	private JCheckBox all = new JCheckBox("All");
	private MyTreeModel model = null;
	private ReturnFrame rframe = null;
	private JXImagePanel imagePanel= null;
	
	
	public JTreeWindow(ControllerPatternFinder controller) {
		super(controller);
		testToRun.add(new JCheckBox("NullPointerFinder"));
		buildFrame();
	}

	
	public void buildFrame(){
		frame.setTitle("Pattern Finder");
		frame.setSize(500, 800);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	    frame.setLocationRelativeTo(null);
	    frame.setResizable(false);
		    
	    container.setBackground(Color.white);
	    frame.setContentPane(container);
	    
	    jtf.setPreferredSize(new Dimension(270,20));
	    jtf.setBackground(colFront);
	    button.addActionListener(this);
	    button2.addActionListener(this);
	    
	    scanBouton.addActionListener(this);
	    //scanBouton.setPreferredSize(new Dimension(50,20));
	    tree = new JTree();
	    tree.setRootVisible(false);
	    BuildTree();
	    tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
	    tree.addTreeSelectionListener(this);

	    progressBar.setValue(0);
	    progressBar.setStringPainted(true);
	    progressBar.setPreferredSize(new Dimension(460,20));
	    progressBar.setBackground(colFront);
	    progressBar.setForeground(Color.darkGray);
	    
	    logText.setPreferredSize(new Dimension(460,130));
	    logText.setEditable(false);
	    logText.setBackground(colFront);
		  
	    all.addActionListener(this);
	    
	    imagePanel = new JXImagePanel();
		try {
		    File file = new File("logica.png");
    		Image image = ImageIO.read(file);
    		image = image.getScaledInstance(294, 130, image.SCALE_DEFAULT);
			imagePanel.setImage(image);
			this.container.add(this.imagePanel);
		} catch (IOException ex) {
			System.err.println(ex.getMessage());
		}
		
	    //organisation des panels
	    
	    JPanel progressPanel = new JPanel();
	    progressPanel.setPreferredSize(new Dimension(480,30));
		progressPanel.add(progressBar);
		
		JPanel DB = new JPanel();
		DB.add(label3);
		DB.add(jtf);
		DB.add(button);
		DB.add(button2);
		DB.setPreferredSize(new Dimension(480,40));
	    
		JPanel allDB = new JPanel();
		allDB.add(DB);
		allDB.add(progressPanel);
		
	    JXTitledPanel remplissageBD = new JXTitledPanel("DataBase");
	    remplissageBD.setBorder(new DropShadowBorder());
	    remplissageBD.setPreferredSize(new Dimension(480,120));
	    remplissageBD.add(allDB);
	    container.add(remplissageBD);
		    
	    
	    
		JScrollPane treePanel = new JScrollPane(tree);
		treePanel.setPreferredSize(new Dimension(460,220));
		
		JPanel checkBoxPanel = new JPanel();
		for(int i = 0 ; i<this.testToRun.size();i++){
			checkBoxPanel.add(testToRun.get(i));
	    }
		checkBoxPanel.setPreferredSize(new Dimension(420,(testToRun.size()/3+1)*30));
		
		JPanel scanPanel = new JPanel();
		scanPanel.add(all);
		scanPanel.add(scanBouton);
		 
		JPanel allScan = new JPanel();
		allScan.add(treePanel);
		allScan.add(checkBoxPanel);
		allScan.add(scanPanel);
		
		JXTitledPanel scan = new JXTitledPanel("Check Pattern");
		scan.setBorder(new DropShadowBorder());
		scan.setPreferredSize(new Dimension(480,340));
		scan.add(allScan);
	    container.add(scan);
		
	    JXTitledPanel logTextPanel = new JXTitledPanel("Results");
	    logTextPanel.setBorder(new DropShadowBorder());
	    logTextPanel.setPreferredSize(new Dimension(480,150));
		logTextPanel.add(logText);
		container.add(logTextPanel,BorderLayout.SOUTH);
		frame.setVisible(true); 
	}
	
	
	private void BuildTree() {
		this.root = new MyTreeNode("Root");
		ArrayList<MyJarNode> jar = this.getController().getJarList();
		for(int j = 0; j<jar.size(); j++ ){
			MyTreeNode category = new MyTreeNode(jar.get(j).getName(),jar.get(j).getId(),jar.get(j).getDate());
			ArrayList<MyPackageNode> pkg = this.getController().getPackageList(jar.get(j).getId().toString());
			for(int k = 0; k<pkg.size(); k++ ){
				MyTreeNode category2 = new MyTreeNode(pkg.get(k).getName(),pkg.get(k).getId());
				ArrayList<MyClassNode> cls = this.getController().getClassList(pkg.get(k).getId().toString());
				for(int i = 0; i<cls.size(); i++ ){
					MyTreeNode category3 = new MyTreeNode(joliNomClasse(cls.get(i).getName()),cls.get(i).getId());
					ArrayList<MyMethodNode> mtd = this.getController().getMethodList(cls.get(i).getId().toString());
					category2.add(category3);
					for(int l = 0; l<mtd.size(); l++ ){
						MyTreeNode category4 = new MyTreeNode(mtd.get(l).getName(),mtd.get(l).getId());
						category3.add(category4);
					}
				}
				category.add(category2);
			}
			this.root.add(category);
		}
		this.model = new MyTreeModel(this.root);
		this.tree.setModel(new DefaultTreeModel(this.root));
	}
	
	public void actionPerformed(ActionEvent e) {
		Object source = e.getSource();
		//Parcourir
		if(source.equals(button)){
			JFileChooser chooser = new JFileChooser();
			int returnVal = chooser.showOpenDialog(jtf);
				if(returnVal == JFileChooser.APPROVE_OPTION) {
					System.out.println("You chose to open this file: " + chooser.getSelectedFile().getPath());
					jtf.setText(chooser.getSelectedFile().getPath());
				}
		}
		//Save
		else if(source.equals(button2)){
	    	this.getController().notifySaveJar(jtf.getText());
	    }
		//Scan
	    else if (source.equals(scanBouton)){
	    	this.logText.setText(null);
	    	try{
	    		MyTreeNode selected = (MyTreeNode)this.tree.getLastSelectedPathComponent();
		    	
	    		ArrayList<String> tests = new ArrayList<String>();
		    	for(int i = 0 ; i<this.testToRun.size();i++){
	    			if (testToRun.get(i).isSelected()){
	    				tests.add(testToRun.get(i).getText());
	    			}
	    	    }
	    		this.getController().notifyRunCheck(tests,selected.getLevel()+"__"+((MyTreeNode)selected).getVersion().toString());	
	    	}catch(Exception error){
	    		System.out.println(error.getMessage());
	    		if (error.getMessage() == null){
	    			this.buildErrorBox("Unknown Error");
	    		}else{
	    			this.buildErrorBox(error.getMessage());
	    		}
	    	}
	    }
		//checkbox All
	    else if (source.equals(all)){
	    	if (this.all.isSelected()){
	    		for(int i = 0 ; i<this.testToRun.size();i++){
	    			testToRun.get(i).setSelected(true);
	    	    }
	    	}
	    }
	}

	@Override
	public void ProgressChanged(ProgressChangedEvent event) {
		int progress = event.getProgress();
		if(progress==100){
			BuildTree();
	    }
	    this.progressBar.setValue(progress);
	}

	@Override
	public void TextChanged(TextChangedEvent event) {
		String text = this.logText.getText();
		this.logText.setText(text + event.getText()+newline);
	}


	@Override
	public void valueChanged(TreeSelectionEvent arg0) {
	}

		

	public String joliNomClasse(String nomMethode){
		String[] arr = nomMethode.split("/");
		String joliMethode = arr[arr.length-1];
		return joliMethode;
	}


	@Override
	public void ReturnArrived(ResultArrivedEvent event) {
		this.model.updateResults(event.getRes());
		this.rframe = new ReturnFrame("Results",this.model);
		
	}
}
